using System.Collections.Generic;
using System.IO;
using System.Linq;
using QFramework;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;

namespace BingoEditor
{
    public class BundleInfo
    {
        public List<string> ParentPaths = new List<string>();
    }

    public enum PlatformType
    {
        None,
        Android,
        IOS,
        PC,
        MacOS,
    }

    public enum BuildType
    {
        Development,
        Release,
    }

    public class BuildEditor: EditorWindow
    {
        private readonly Dictionary<string, BundleInfo> dictionary = new Dictionary<string, BundleInfo>();

        private PlatformType platformType = PlatformType.Android;
        private bool isBuildExe = true;
        private bool isContainAB = true;
        private bool isBinary;
        private BuildType buildType = BuildType.Release;
        private BuildOptions buildOptions = BuildOptions.AllowDebugging | BuildOptions.Development;
        private BuildAssetBundleOptions buildAssetBundleOptions = BuildAssetBundleOptions.None;

        [MenuItem("Tools/打包")]
        public static void ShowWindow()
        {
            GetWindow(typeof(BuildEditor));
        }

        private void OnGUI()
        {
            this.platformType = (PlatformType) EditorGUILayout.EnumPopup(platformType);
            this.isBuildExe = true;// EditorGUILayout.Toggle("�Ƿ���EXE: ", this.isBuildExe);
            this.isContainAB = true;// EditorGUILayout.Toggle("�Ƿ�ͬ����Դ���EXE: ", this.isContainAB);
            this.isBinary = EditorGUILayout.Toggle("是否二进制", this.isBinary);
            this.buildType = (BuildType) EditorGUILayout.EnumPopup("BuildType: ", this.buildType);

            switch (buildType)
            {
                case BuildType.Development:
                    this.buildOptions = BuildOptions.Development | BuildOptions.AutoRunPlayer | BuildOptions.ConnectWithProfiler |
                                        BuildOptions.AllowDebugging;
                    break;
                case BuildType.Release:
                    this.buildOptions = BuildOptions.None;
                    break;
            }

            this.buildAssetBundleOptions =  (BuildAssetBundleOptions) EditorGUILayout.EnumFlagsField("BuildAssetBundleOptions(none): ", this.buildAssetBundleOptions);

            if (GUILayout.Button("开始打包"))
            {
                if (this.platformType == PlatformType.None)
                {
                    Log.E("请选择打包平台̨!");
                    return;
                }

                if (this.platformType == PlatformType.Android)
                {
                    //����Android keystone·��
                    PlayerSettings.Android.keyaliasName = "bingo";
                    PlayerSettings.Android.keyaliasPass = "123456";
                    PlayerSettings.Android.keystorePass = "123456";
                }

                BuildHelper.Build(this.platformType, this.buildAssetBundleOptions, this.buildOptions, this.isBuildExe, this.isContainAB, this.isBinary);
            }
        }

        private void SetPackingTagAndAssetBundle()
        {
            ClearPackingTagAndAssetBundle();

            SetIndependentBundleAndAtlas("Assets/Bundles/Independent");

            SetBundleAndAtlasWithoutShare("Assets/Bundles/UI");

            SetRootBundleOnly("Assets/Bundles/Unit");

            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
        }

        private static void SetNoAtlas(string dir)
        {
            List<string> paths = EditorResHelper.GetPrefabsAndScenes(dir);

            foreach (string path in paths)
            {
                List<string> pathes = CollectDependencies(path);

                foreach (string pt in pathes)
                {
                    if (pt == path)
                    {
                        continue;
                    }

                    SetAtlas(pt, "", true);
                }
            }
        }

        // �ὫĿ¼�µ�ÿ��prefab���õ���Դ���һ����,ֻ������prefab���
        private static void SetRootBundleOnly(string dir)
        {
            List<string> paths = EditorResHelper.GetPrefabsAndScenes(dir);
            foreach (string path in paths)
            {
                string path1 = path.Replace('\\', '/');
                Object go = AssetDatabase.LoadAssetAtPath<Object>(path1);

                SetBundle(path1, go.name);
            }
        }

        // �ὫĿ¼�µ�ÿ��prefab���õ���Դǿ�ƴ��һ������������������Դ
        private static void SetIndependentBundleAndAtlas(string dir)
        {
            List<string> paths = EditorResHelper.GetPrefabsAndScenes(dir);
            foreach (string path in paths)
            {
                string path1 = path.Replace('\\', '/');
                Object go = AssetDatabase.LoadAssetAtPath<Object>(path1);

                AssetImporter importer = AssetImporter.GetAtPath(path1);
                if (importer == null || go == null)
                {
                    Log.E("error: " + path1);
                    continue;
                }

                importer.assetBundleName = $"{go.name}.unity3d";

                List<string> pathes = CollectDependencies(path1);

                foreach (string pt in pathes)
                {
                    if (pt == path1)
                    {
                        continue;
                    }

                    SetBundleAndAtlas(pt, go.name, true);
                }
            }
        }

        private static void SetBundleAndAtlasWithoutShare(string dir)
        {
            List<string> paths = EditorResHelper.GetPrefabsAndScenes(dir);
            foreach (string path in paths)
            {
                string path1 = path.Replace('\\', '/');
                Object go = AssetDatabase.LoadAssetAtPath<Object>(path1);

                SetBundle(path1, go.name);
            }
        }

        private static List<string> CollectDependencies(string o)
        {
            string[] paths = AssetDatabase.GetDependencies(o);

            //Log.Debug($"{o} dependecies: " + paths.ToList().ListToString());
            return paths.ToList();
        }


        private static void ClearPackingTagAndAssetBundle()
        {
            //List<string> bundlePaths = EditorResHelper.GetAllResourcePath("Assets/Bundles/", true);
            //foreach (string bundlePath in bundlePaths)
            //{
            //	SetBundle(bundlePath, "", true);
            //}

            List<string> paths = EditorResHelper.GetAllResourcePath("Assets/Res", true);
            foreach (string pt in paths)
            {
                SetBundleAndAtlas(pt, "", true);
            }
        }

        private static string GetBundleName(string path)
        {
            string extension = Path.GetExtension(path);
            if (extension == ".cs" || extension == ".dll" || extension == ".js")
            {
                return "";
            }

            if (path.Contains("Resources"))
            {
                return "";
            }

            AssetImporter importer = AssetImporter.GetAtPath(path);
            if (importer == null)
            {
                return "";
            }

            return importer.assetBundleName;
        }

        private static void SetBundle(string path, string name, bool overwrite = false)
        {
            string extension = Path.GetExtension(path);
            if (extension == ".cs" || extension == ".dll" || extension == ".js")
            {
                return;
            }

            if (path.Contains("Resources"))
            {
                return;
            }

            AssetImporter importer = AssetImporter.GetAtPath(path);
            if (importer == null)
            {
                return;
            }

            if (importer.assetBundleName != "" && overwrite == false)
            {
                return;
            }

            //Log.Info(path);
            string bundleName = "";
            if (name != "")
            {
                bundleName = $"{name}.unity3d";
            }

            importer.assetBundleName = bundleName;
        }

        private static void SetAtlas(string path, string name, bool overwrite = false)
        {
            string extension = Path.GetExtension(path);
            if (extension == ".cs" || extension == ".dll" || extension == ".js")
            {
                return;
            }

            if (path.Contains("Resources"))
            {
                return;
            }

            TextureImporter textureImporter = AssetImporter.GetAtPath(path) as TextureImporter;
            if (textureImporter == null)
            {
                return;
            }

            if (textureImporter.spritePackingTag != "" && overwrite == false)
            {
                return;
            }

            textureImporter.spritePackingTag = name;
            AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
        }

        private static void SetBundleAndAtlas(string path, string name, bool overwrite = false)
        {
            string extension = Path.GetExtension(path);
            if (extension == ".cs" || extension == ".dll" || extension == ".js" || extension == ".mat")
            {
                return;
            }

            if (path.Contains("Resources"))
            {
                return;
            }

            AssetImporter importer = AssetImporter.GetAtPath(path);
            if (importer == null)
            {
                return;
            }

            if (importer.assetBundleName == "" || overwrite)
            {
                string bundleName = "";
                if (name != "")
                {
                    bundleName = $"{name}.unity3d";
                }

                importer.assetBundleName = bundleName;
            }

            TextureImporter textureImporter = importer as TextureImporter;
            if (textureImporter == null)
            {
                return;
            }

            if (textureImporter.spritePackingTag == "" || overwrite)
            {
                textureImporter.spritePackingTag = name;
                AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
            }
        }

        [MenuItem("Tools/清除数据")]
        public static void DeleteAllData()
        {
            PlayerPrefs.DeleteAll();

            string folder = Application.persistentDataPath;
            Debug.Log("---> Application.persistentDataPath : " +Application.persistentDataPath);
            if (Directory.Exists(folder))
            {
                Directory.Delete(folder, true);
            }
        }
    }
}